<?php
  // load classes
  require_once dirname(__FILE__) . '/includes/MiscUtils.class.php';
  require_once dirname(__FILE__) . '/metadata.php';
  require_once dirname(__FILE__) . '/config.php';
  require_once dirname(__FILE__) . '/DbUtils.class.php';
  require_once dirname(__FILE__) . '/sync_server.class.php';
  
  $myPdo = DbUtils::createPdoInst();
  global $myPdo;
  
  $clientLibraryPath = SERVER_ROOT . PATH . 'libs/ZendGdata/library';
  $oldPath = set_include_path(get_include_path() . PATH_SEPARATOR . $clientLibraryPath);
  
  require_once 'Zend/Loader.php';
  Zend_Loader::loadClass('Zend_Gdata');
  Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
  Zend_Loader::loadClass('Zend_Gdata_Calendar');
  Zend_Loader::loadClass('Zend_Http_Client');
      
// create authenticated HTTP client for Calendar service
  $gcal = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
  $user = GMAIL_USER;
  $pass = GMAIL_PASS;
  
  $offset = getOffsetTime(DATE_ZONE);
  $tzOffset = ($offset > 0) ? ((abs($offset) < 10) ? "+0" . abs($offset) : "+" . abs($offset)) : ((abs($offset) < 10) ? "-0" . abs($offset) : "-" . abs($offset));
  
  try {
    $client = Zend_Gdata_ClientLogin::getHttpClient($user,$pass,$gcal);
  } catch(Zend_Gdata_App_Exception $e) {
    die('Error1:' . $e->getMessage());
  }
  
  $start = date('Y-m-d', time() - 86400*3);
  $end = date('Y-m-d', strtotime('+3 month'));
    
  try {
  	$gcal = new Zend_Gdata_Calendar($client);
  
  	$min_start = $start . "T00:00:00.000$tzOffset:00";
    $max_start = $end . "T00:00:00.000$tzOffset:00";
    
	  $query = $gcal->newEventQuery();
	  $query->setOrderby('starttime');
	  $query->setUser('default');
	  $query->setVisibility('private');
	  $query->setProjection('full');
	  $query->setStartMin($min_start);
    $query->setStartMax($max_start);
	  $query->setMaxResults (999999);
	  
	
	  $add_to_google = array();
	  $deleted_from_google = array();
	  $add_to_us = array();
	  $deleted_from_us = array();
	  $updated_to_us = array();
	  $updated_to_google = array();
	  $results = array();
	  $feeds = array();
	  $us_evt_map = array();
	  $gg_evt_map = array();
    $feeds = $gcal->getCalendarEventFeed($query);
    
  } catch(Zend_Gdata_App_Exception $e) {
    die('Error2: ' . $e->getMessage());
  }
  
  try {
  	$cond_vals = new stdClass();
  	$cond_vals->c = 't.start >= :v1 AND t.start <= :v2';
  	$cond_vals->v = array(':v1' => $start, ':v2' => $end);
    $results = DbUtils::get($myPdo, TABLE_NAME_PREFIX_PLUGIN . 'calendar_event', $cond_vals, 't.start', 'DESC', NULL, NULL, NULL)->d;
    
  } catch(PDOException $e) {
  	die('Error3: ' . $e->getMessage());
  }
  
  try {
    foreach ($results as &$us_evt) {
      if ($us_evt->google_id != '') {
        $us_evt_map[$us_evt->google_id] = $us_evt;
      }
    }
    foreach ($feeds as $gg_evt) {
      $gg_evt_map[$gg_evt->id->text] = $gg_evt;
    }
    
    foreach ($results as &$us_evt) {
      if ($us_evt->google_id == '' && $us_evt->is_deleted == 0) {
        $gg_evt = NULL;
        $add_to_google[] = get_gg_evt($us_evt, $gg_evt, $gcal, $tzOffset);
      }
    }
    //$add_to_google[]
    
    foreach ($feeds as $gg_evt) {
      if (is_not_in_us($gg_evt, $us_evt_map)) {
      	$us_evt = NULL;
        $add_to_us[] = get_us_evt($gg_evt, $us_evt);
      }
    }
    //$add_to_us[]
    
    foreach ($results as &$us_evt) {
      if ($us_evt->is_deleted == 1) {
        $gg_evt = find_gg_evt($us_evt, $gg_evt_map);
        if (isset($gg_evt)) {
          $deleted_from_google[] = $gg_evt;
        }
      }
    }
    //$deleted_from_google[]
    
    foreach ($results as &$us_evt) {
      if ($us_evt->is_deleted == 1) {
        $deleted_from_us[] = $us_evt;
      }
      if ($us_evt->google_id != '' && is_not_in_gg($us_evt, $gg_evt_map)) {
        $deleted_from_us[] = $us_evt;
      }
    }
    //$deleted_from_us[]
   
    foreach ($feeds as $gg_evt) {
      $us_evt = find_us_evt($gg_evt, $us_evt_map);
      if (isset($us_evt)) {
        $gg_tmp =  explode(".", $gg_evt->updated->text);
        $gg_tmp1 = str_replace('T', ' ', strval($gg_tmp[0]));
        if (strtotime($gg_tmp1) > strtotime($us_evt->last_updated)) {
          $updated_to_us[] = get_us_evt($gg_evt, $us_evt);
        }
      }
    }
    //$updated_to_us[]
    
    foreach ($results as &$us_evt) {
      if ($us_evt->is_google_updated == 0) {
      	$gg_evt = find_gg_evt($us_evt, $gg_evt_map);
        if (isset($gg_evt)) {
          $updated_to_google[] = get_gg_evt($us_evt, $gg_evt, $gcal, $tzOffset);
        }
      }
    }
    //$updated_to_google[]
    
  } catch(PDOException $e) {
    echo ('Error4: ' . $e->getMessage());
  }
  
  $to_update = array();
  foreach ($add_to_google as $key => $tmp1) {
	  try {
	    $event = $gcal->insertEvent($tmp1->gg_evt);
      $tmp1->us_evt->google_id = $event->id->text;
	    $tmp1->us_evt->last_updated = date('Y-m-d H:i:s', time()+10);
	    $to_update[] = $tmp1->us_evt;
	  } catch(Zend_Gdata_App_Exception $e) {
	    echo 'Error5: ' . $e->getMessage();
	  }
  }
  
  try {
    foreach ($updated_to_google as &$tmp6) {
      $tmp6->gg_evt->save();
      $tmp6->us_evt->is_google_updated = 1;
      $tmp6->us_evt->last_updated = date('Y-m-d H:i:s', time()+10);
      $to_update[] = $tmp6->us_evt;
    }
  } catch(Zend_Gdata_App_Exception $e) {
    echo 'Error10: ' . $e->getMessage();
  }
  
  try {
    foreach ($deleted_from_google as &$tmp2) {
      $tmp2->delete();
    }
  } catch(Zend_Gdata_App_Exception $e) {
    echo 'Error6: ' . $e->getMessage();
  }
  
  try {
  	$msgs = array();
    $enqs = array();
    $enq_msgs = array();
    $msg_table = TABLE_NAME_PREFIX_MODULE . 'data_email_messages';
    $enq_table = TABLE_NAME_PREFIX_MODULE . 'data_enquiry';
    
    $cond_vals1 = new stdClass();
    $cond_vals1->c = '';
    
    $o_events = array();
    $tmpps = array_merge($deleted_from_us, $updated_to_us);
    foreach ($tmpps as &$tmpp) {
      if ($tmpp->message_id != 0) {
        $o_events[] = $tmpp;
      }
    }
    foreach ($o_events as $key => $tp) {
      $cond_vals1->c .= 't.id = ' . $tp->message_id;
      if ($key < count($o_events) - 1) {
        $cond_vals1->c .= ' OR ';
      }
    }
    if ($cond_vals1->c != '' ) {
	    $cond_vals1->c = '(' . $cond_vals1->c . ') AND t.parent_id = 0';
	    $cond_vals1->v = array();
	    $opts1 = new stdClass();
	    $opts1->select_expr = 'Distinct t.id, t.attr2, t.appointment_date, t.appt_user_id, t.appt_user_name, t.appointment_note, t.is_visited, t.reminding_date, t.reminding_type, t.reminding_days, t.reminding_note, t.is_reminding_closed, t.reminding_closed_date';
	    $msgs = DbUtils::get($myPdo, $msg_table, $cond_vals1, 't.date1', 'DESC', NULL, NULL, $opts1)->d;
    }
    
    $cond_vals2 = new stdClass();
    $cond_vals2->c = '';
    foreach ($msgs as $key => $msg) {
      $cond_vals2->c .= 't.id = ' . $msg->attr2;
      if ($key < count($msgs) - 1) {
        $cond_vals2->c .= ' OR ';
      }
    }
    
    if ($cond_vals2->c != '' ) {
	    $cond_vals2->v = array();
	    $opts2 = new stdClass();
	    $opts2->select_expr = 'Distinct t.id, t.appointment_date, t.appointment_status';
	    $enqs = DbUtils::get($myPdo, $enq_table, $cond_vals2, 't.id', 'ASC', NULL, NULL, $opts2)->d;
    }
    
    $cond_vals3 = new stdClass();
    $cond_vals3->c = '';
    foreach ($enqs as $key => $enq) {
      $cond_vals3->c .= 't.attr2 = ' . $enq->id;
      if ($key < count($enqs) - 1) {
        $cond_vals3->c .= ' OR ';
      }
    }
    
    if ($cond_vals3->c != '') {
	    $cond_vals3->c = '(' . $cond_vals3->c . ') AND t.parent_id = 0 AND t.is_draft = 0';
	    $cond_vals3->v = array();
	    $opts3 = new stdClass();
	    $opts3->select_expr = 'Distinct t.id, t.appointment_date, t.is_visited';
	    $enq_msgs = DbUtils::get($myPdo, $msg_table, $cond_vals3, 't.date1', 'DESC', NULL, NULL, $opts3)->d;
    }
    
  } catch (PDOException $e) {
    echo ("Error12: " . MiscUtils::dump($e));
  }
  
  try {
  	$myPdo1 = DbUtils::createPdoInst();
  	
    $myPdo1->beginTransaction();
    $table = TABLE_NAME_PREFIX_PLUGIN . 'calendar_event';
    
    foreach ($add_to_us as &$tmp3) {
      DbUtils::add($myPdo1, $table, $tmp3);
    }
    
    foreach ($to_update as &$obj) {
      DbUtils::update($myPdo1, $table, $obj);
    }
    
    foreach ($updated_to_us as &$tmp5) {
      if (count($msgs) > 0) {
        Server::changeMsg($myPdo1, 2, $tmp5, $msgs, $enqs, $enq_msgs);
      }
      DbUtils::update($myPdo1, $table, $tmp5);
    }

    foreach ($deleted_from_us as &$tmp4) {
      if (count($msgs) > 0) {
        Server::changeMsg($myPdo1, 1, $tmp4, $msgs, $enqs, $enq_msgs);
      }
      DbUtils::delete($myPdo1, $table, $tmp4);
    }
  
    $myPdo1->commit();
    
  } catch (PDOException $e) {
  	try {
      $myPdo1->rollBack();
  	} catch (PDOException $e1) {
  	  echo "Error11: " . MiscUtils::dump($e1);
  	}
    die("Error7,8,9: " . MiscUtils::dump($e));
  }
  
  function getOffsetTime($zone) {
    $dateTimeZone = new DateTimeZone($zone);
    $dateTimeZoneUTC = new DateTimeZone('UTC');
    $dateTime = new DateTime("now", $dateTimeZone);
    $dateTimeUTC = new DateTime("now", $dateTimeZoneUTC);
    $timeOffset = $dateTimeZone->getOffset($dateTime) - $dateTimeZoneUTC->getOffset($dateTimeUTC); 
    return ($timeOffset / 3600);
  }
  
  function is_not_in_us($gg_evt, $us_evt_map) {
    if (!isset($us_evt_map[$gg_evt->id->text])) {
    	return true;
    } else {
    	return false;
    }
  }
  
  function is_not_in_gg($us_evt, $gg_evt_map) {
    if (!isset($gg_evt_map[$us_evt->google_id])) {
      return true;
    } else {
      return false;
    }
  }
  
  function find_us_evt($gg_evt, $us_evt_map) {
    return $us_evt_map[$gg_evt->id->text];
  }
  
  function find_gg_evt($us_evt, $gg_evt_map) {
    return $gg_evt_map[$us_evt->google_id];
  }
  
  function get_gg_evt($us_evt, $gg_evt, $gcal, $tzOffset) {
  	$title = $us_evt->title;
    $content = $us_evt->description;
    if ($us_evt->allDay) {
      $start = date("Y-m-d", strtotime($us_evt->start));
      $end = date("Y-m-d", strtotime($us_evt->end) + 86400);
    } else {
      $s_tmp1 =  split(" ", $us_evt->start);
      $e_tmp1 =  split(" ", $us_evt->end);
    
      $start = "$s_tmp1[0]T$s_tmp1[1].000$tzOffset:00";
      $end = "$e_tmp1[0]T$e_tmp1[1].000$tzOffset:00";
    }
    $method = ($us_evt->remind_type == '') ? 'none' : 'email';
    $minutes = ($us_evt->remind_type == '') ? '0' : '1';
    
  	if (isset($gg_evt)) {
  	  $gg_evt->title = $gcal->newTitle($title);
      $gg_evt->content = $gcal->newContent($content);
      $when = $gcal->newWhen();
      $when->startTime = $start;
      $when->endTime = $end;
      $reminder = $gcal->newReminder();
      $reminder->method = "$method";
      $reminder->minutes = "$minutes";
      $when->reminders = array($reminder);
      $gg_evt->when = array($when);
  	} else {
  	  $gg_evt = $gcal->newEventEntry();
	    $gg_evt->title = $gcal->newTitle($title);
	    $gg_evt->content = $gcal->newContent($content);
	    $when = $gcal->newWhen();
	    $when->startTime = $start;
	    $when->endTime = $end;
	    $reminder = $gcal->newReminder();
	    $reminder->method = "$method";
	    $reminder->minutes = "$minutes";
	    $when->reminders = array($reminder);
	    $gg_evt->when = array($when);
  	}
    
    $final = new stdClass();
    $final->us_evt = $us_evt;
    $final->gg_evt = $gg_evt;
    return $final;
  }
  
  function get_us_evt($gg_evt, $us_evt) {
    if (strlen($gg_evt->when[0]->startTime) == 10) {
      $s_tmp2 = date("Y-m-d", strtotime($gg_evt->when[0]->startTime)) . ' 00:00:00';
      $e_tmp2 = date("Y-m-d", strtotime($gg_evt->when[0]->endTime) - 86400) . ' 23:59:00';
      $allday = 1;
    } else {
      $s_tmp1 =  explode(".", $gg_evt->when[0]->startTime);
      $e_tmp1 =  explode(".", $gg_evt->when[0]->endTime);
      $search = 'T';
      $replace = ' ';
      $str1 = strval($s_tmp1[0]);
      $str2 = strval($e_tmp1[0]);
      if (count($s_tmp1) > 0) {
        $s_tmp2 = str_replace($search, $replace, $str1);
      }
      if (count($e_tmp1) > 0) {
        $e_tmp2 = str_replace($search, $replace, $str2);
      }
      $allday = 0;
    }
    
    if (isset($gg_evt->when[0]->reminders[0])) {
      $remind_type = '1';
      $remind_minute = 0;
    } else {
      $remind_type = '';
      $remind_minute = 0;
    }
    
    if (isset($us_evt)) {
    	$us_evt->title = $gg_evt->title->text;
      $us_evt->start = $s_tmp2;
      $us_evt->end = $e_tmp2;
      $us_evt->description = $gg_evt->content->text;
      $us_evt->remind_type = $remind_type;
      $us_evt->remind_minute = $remind_minute;
      $us_evt->allDay = $allday;
      $us_evt->last_updated = date('Y-m-d H:i:s', time());
    } else {
	    $us_evt = new stdClass();
	    $us_evt->track_id = MiscUtils::unique();
	    $us_evt->title = $gg_evt->title->text;
	    $us_evt->start = $s_tmp2;
	    $us_evt->end = $e_tmp2;
	    $us_evt->google_id = $gg_evt->id->text;
	    $us_evt->description = $gg_evt->content->text;
	    $us_evt->remind_type = $remind_type;
	    $us_evt->remind_minute = $remind_minute;
	    $us_evt->allDay = $allday;
	    $us_evt->type = 0;
	    $us_evt->message_id = 0;
	    $us_evt->is_deleted = 0;
	    $us_evt->is_updated = 0;
	    $us_evt->is_google_updated = 1;
	    $us_evt->last_updated = date('Y-m-d H:i:s', time());
    }
    return $us_evt;
  }
?>